﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media.Animation;

namespace MineBoxRelease.Custom
{
    class DraggableScrollViewer : ScrollViewer
    {
        //拖拽方向枚举类型
        public enum OrientationType
        {
            Horizontal, Vertical, All
        }
        //拖拽开始点
        private Point startPoint;
        //启用/禁止拖拽
        public bool Draggable { get; set; }
        //拖拽方向
        public OrientationType Orientation { get; set; }

        //偏移属性
        internal static readonly DependencyProperty ScrollViewerVerticalOffsetProperty =
            DependencyProperty.Register("ScrollViewerVerticalOffset", typeof(double), typeof(DraggableScrollViewer), new FrameworkPropertyMetadata(VerticalOffsetChanged));
        internal static readonly DependencyProperty ScrollViewerHorizontalOffsetProperty =
            DependencyProperty.Register("ScrollViewerHorizontalOffset", typeof(double), typeof(DraggableScrollViewer), new FrameworkPropertyMetadata(HorizontalOffsetChanged));

        private static void VerticalOffsetChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            DraggableScrollViewer viewer = (DraggableScrollViewer)obj;
            viewer.ScrollToVerticalOffset((double)e.NewValue);
        }
        private static void HorizontalOffsetChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
        {
            DraggableScrollViewer viewer = (DraggableScrollViewer)obj;
            viewer.ScrollToHorizontalOffset((double)e.NewValue);
        }

        public DraggableScrollViewer()
        {
            CanContentScroll = false;
            Draggable = true;
            Orientation = OrientationType.Vertical;
        }

        //鼠标滚轮平滑滚动
        protected override void OnPreviewMouseWheel(MouseWheelEventArgs e)
        {
            //base.OnPreviewMouseWheel(e);
            Storyboard sb = new Storyboard();
            if (Orientation == OrientationType.Vertical || Orientation == OrientationType.All)
            {
                var da = new DoubleAnimation
                {
                    To = VerticalOffset - e.Delta * 1.5,
                    Duration = TimeSpan.FromSeconds(0.4),
                    EasingFunction = new CircleEase { EasingMode = EasingMode.EaseOut }
                };
                Storyboard.SetTarget(da, this);
                Storyboard.SetTargetProperty(da, new PropertyPath(ScrollViewerVerticalOffsetProperty));
                sb.Children.Add(da);
            }
            else
            {
                var da = new DoubleAnimation
                {
                    To = HorizontalOffset - e.Delta * 1.5,
                    Duration = TimeSpan.FromSeconds(0.4),
                    EasingFunction = new CircleEase { EasingMode = EasingMode.EaseOut }
                };
                Storyboard.SetTarget(da, this);
                Storyboard.SetTargetProperty(da, new PropertyPath(ScrollViewerHorizontalOffsetProperty));
                sb.Children.Add(da);
            }

            sb.Begin();
            e.Handled = true;
        }

        //鼠标拖拽开始
        protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e)
        {
            base.OnPreviewMouseLeftButtonDown(e);
            startPoint = e.GetPosition(this);
        }

        //鼠标拖拽移动
        protected override void OnPreviewMouseMove(MouseEventArgs e)
        {
            base.OnPreviewMouseMove(e);
            if (!Draggable || e.LeftButton != MouseButtonState.Pressed) return;
            Point curPoint = e.GetPosition(this);
            if (Orientation == OrientationType.Vertical)
            {
                double deltaY = startPoint.Y - curPoint.Y;
                ScrollToVerticalOffset(VerticalOffset + deltaY);
            }
            else
            {
                double deltaX = startPoint.X - curPoint.X;
                ScrollToHorizontalOffset(HorizontalOffset + deltaX);
            }
            startPoint = curPoint;
        }
    }
}
